package adc.app.ui.wicket;

import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow.CloseButtonCallback;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.request.resource.PackageResourceReference;
import org.apache.wicket.spring.injection.annot.SpringBean;

import adc.app.spec.IAutheBs;
import adc.app.spec.IUser;
import adc.app.ui.wicket.ChangeLocaleLink.IChangeLocaleCallback;
import adc.app.ui.wicket.ChangePasswordLink.IChangePasswordCallback;
import adc.app.ui.wicket.ChangePasswordPanel.IPasswordChangedCallback;
import adc.app.ui.wicket.ChangePasswordPanel.IQuitChangePasswordCallback;
import adc.app.ui.wicket.security.LoginPanel;
import adc.app.ui.wicket.security.LogoutLink;
import adc.app.ui.wicket.security.LoginPanel.ILoginCallback;

public abstract class AbstractLayoutPage extends WebPage implements ILoginCallback, IChangePasswordCallback,
        IPasswordChangedCallback, IQuitChangePasswordCallback, IChangeLocaleCallback {

    private static final long serialVersionUID = 1L;

    private static final String ID_MODAL_WIDOW = "modalWindow";

    private static final String COMP_ID_DOCK_NAV_ITEM = "dockNavigationItem";
    private static final String COMP_ID_NAV_ITEM = "navigationItem";
    private static final String COMP_ID_FOOTER = "footer";

    private final RepeatingView dockNavRV = new RepeatingView(COMP_ID_DOCK_NAV_ITEM);
    private final RepeatingView navRV = new RepeatingView(COMP_ID_NAV_ITEM);

    private Label windowTitle = new Label("windowTitle"), pageTitle = new Label("pageTitle");

    {
        add(dockNavRV).add(navRV).add(createFooter(COMP_ID_FOOTER));
        add(new ModalWindow(ID_MODAL_WIDOW).setCssClassName(ModalWindow.CSS_CLASS_GRAY));

        add(new PopupLoginBehavior()).add(new ReloadBehavior().setParameters(this.getPageParameters()));
        add(new Label("applicationTitle", new ResourceModel(getAppNameKey())).setRenderBodyOnly(true));
        add(windowTitle.setRenderBodyOnly(true)).add(pageTitle.setRenderBodyOnly(true));

        addMenus(navRV);

        dockNavRV.add(new ChangeLocaleLink(dockNavRV.newChildId()).setCallback(this));
        dockNavRV.add(new ChangePasswordLink(dockNavRV.newChildId()).setCallback(this));
        dockNavRV.add(new LogoutLink(dockNavRV.newChildId()));
    }

    @SpringBean
    private IAutheBs<IUser> authBS;

    protected AbstractLayoutPage() {
        super();
    }

    protected AbstractLayoutPage(IModel<?> model) {
        super(model);
    }

    protected AbstractLayoutPage(PageParameters parameters) {
        super(parameters);
    }

    public final ModalWindow getModalWindow() {
        return (ModalWindow) this.get(ID_MODAL_WIDOW);
    }

    protected Component createFooter(String id) {
        return new WebComponent(id);
    }

    public final IModel<?> getTitle() {
        return windowTitle.getDefaultModel();
    }

    public final AbstractLayoutPage setTitle(IModel<?> title) {
        this.windowTitle.setDefaultModel(title);
        this.pageTitle.setDefaultModel(title);
        return this;
    }

    @Override
    public void renderHead(HtmlHeaderContainer container) {
        super.renderHead(container);

        container.getHeaderResponse().renderCSSReference(
                new PackageResourceReference(AbstractLayoutPage.class, "css/layout.css"), "screen");
        container.getHeaderResponse().renderCSSReference(
                new PackageResourceReference(AbstractLayoutPage.class, "css/forms.css"), "screen");
        container.getHeaderResponse().renderCSSReference(
                new PackageResourceReference(AbstractLayoutPage.class, "css/tables.css"), "screen");
        container.getHeaderResponse().renderCSSReference(
                new PackageResourceReference(AbstractLayoutPage.class, "css/panels.css"), "screen");
        container.getHeaderResponse().renderCSSReference(
                new PackageResourceReference(AbstractLayoutPage.class, "css/others.css"), "screen");

    }

    @Override
    public void onLogin(AjaxRequestTarget target, IUser user) {
        this.getModalWindow().close(target);
        this.getModalWindow().setCloseButtonCallback(null);
        ReloadBehavior reload = this.getBehaviors(ReloadBehavior.class).get(0);
        target.appendJavaScript(reload.getCallbackScript());

    }

    @Override
    public void onChangePassword(AjaxRequestTarget target) {
        int width = 260, height = 156;
        this.getModalWindow().setContent(
                new ChangePasswordPanel(this.getModalWindow().getContentId()).setPasswordChangedCallback(this)
                        .setQuitCallback(this)).setInitialWidth(width).setMinimalWidth(width).setInitialHeight(height)
                .setMinimalHeight(height).setTitle(new ResourceModel(IMsgs.CHANGE_PASSWORD)).show(target);
    }

    @Override
    public void onQuitChangePassword(AjaxRequestTarget target) {
        this.getModalWindow().close(target);
    }

    @Override
    public void onPasswordChanged(AjaxRequestTarget target) {
        this.getModalWindow().close(target);
    }

    @Override
    public void onChangeLocale(AjaxRequestTarget target) {
        ReloadBehavior reload = this.getBehaviors(ReloadBehavior.class).get(0);
        target.appendJavaScript(reload.getCallbackScript());
    }

    protected abstract void addMenus(RepeatingView menus);

    protected abstract String getAppNameKey();

    private static final class PopupLoginBehavior extends AbstractDefaultAjaxBehavior {

        private static final long serialVersionUID = 1L;

        

        @Override
        public void renderHead(Component component, IHeaderResponse response) {
            super.renderHead(component, response);
            response.renderOnDomReadyJavaScript(String.valueOf(this.getCallbackScript()));
        }

        @Override
        protected void respond(AjaxRequestTarget target) {
            AbstractLayoutPage page = (AbstractLayoutPage) this.getComponent();
            ModalWindow modalWindow = page.getModalWindow();
            modalWindow.setTitle(new ResourceModel(IMsgs.LOGIN));
            modalWindow.setCloseButtonCallback(new PreventCloseWindowCallback());
            int width = 305, height = 122;
            modalWindow.setMinimalWidth(width).setMinimalHeight(height).setInitialWidth(width).setInitialHeight(height);
            modalWindow.setContent(new LoginPanel(modalWindow.getContentId()).setCallback(page));
            modalWindow.show(target);
        }

        @Override
        public boolean isEnabled(Component component) {
            AbstractLayoutPage page = (AbstractLayoutPage) component;
            return super.isEnabled(component) && !page.authBS.isAuthenticated();
        }

    }

    private static final class ReloadBehavior extends AbstractDefaultAjaxBehavior {

        private static final long serialVersionUID = 1L;

        private PageParameters parameters;

        @SuppressWarnings("unchecked")
        @Override
        protected void respond(AjaxRequestTarget target) {
            target.appendJavaScript("window.location.href='"
                            + RequestCycle.get().urlFor((Class<Page>) target.getPage().getClass(), parameters)
                                    .toString() + "'");
        }

        public ReloadBehavior setParameters(PageParameters parameters) {
            this.parameters = parameters;
            return this;
        }

        @Override
        public String getCallbackScript() {
            return super.getCallbackScript().toString();
        }
    }

    private static final class PreventCloseWindowCallback implements CloseButtonCallback {

        private static final long serialVersionUID = 1L;

        @Override
        public boolean onCloseButtonClicked(AjaxRequestTarget target) {
            return false;
        }
    }
}